/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.app.record.service.impl;

import me.zhengjie.modules.app.record.domain.RecordDetailInfo;
import me.zhengjie.modules.app.record.domain.RecordInfo;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.app.record.repository.RecordInfoRepository;
import me.zhengjie.modules.app.record.service.RecordInfoService;
import me.zhengjie.modules.app.record.service.dto.RecordInfoDto;
import me.zhengjie.modules.app.record.service.dto.RecordInfoQueryCriteria;
import me.zhengjie.modules.app.record.service.mapstruct.RecordInfoMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.SecurityUtils;

import java.util.List;
import java.util.Map;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.LinkedHashMap;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author Haojie Li
* @date 2021-03-03
**/
@Service
@RequiredArgsConstructor
public class RecordInfoServiceImpl implements RecordInfoService {

    private final RecordInfoRepository recordInfoRepository;
    private final RecordInfoMapper recordInfoMapper;

    @Override
    public Map<String,Object> queryAll(RecordInfoQueryCriteria criteria, Pageable pageable){
        Page<RecordInfo> page = recordInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(recordInfoMapper::toDto));
    }

    @Override
    public List<RecordInfoDto> queryAll(RecordInfoQueryCriteria criteria){
        return recordInfoMapper.toDto(recordInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public RecordInfoDto findById(String id) {
        RecordInfo recordInfo = recordInfoRepository.findById(id).orElseGet(RecordInfo::new);
        ValidationUtil.isNull(recordInfo.getId(),"RecordInfo","id",id);
        return recordInfoMapper.toDto(recordInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RecordInfoDto create(RecordInfo resources) {
        resources.setId(IdUtil.simpleUUID());
        resources.setCreateBy(SecurityUtils.getCurrentUsername());
        resources.setCreateTime(LocalDateTime.now());
        resources.setIsEnable(1);
        return recordInfoMapper.toDto(recordInfoRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(RecordInfo resources) {
    	resources.setUpdateBy(SecurityUtils.getCurrentUsername());
    	resources.setUpdateTime(LocalDateTime.now());

        RecordInfo recordInfo = recordInfoRepository.findById(resources.getId()).orElseGet(RecordInfo::new);
        ValidationUtil.isNull( recordInfo.getId(),"RecordInfo","id",resources.getId());
        recordInfo.copy(resources);
        recordInfoRepository.save(recordInfo);
    }

    @Override
    public void deleteAll(String[] ids) {
        for (String id : ids) {
            recordInfoRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<RecordInfoDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (RecordInfoDto recordInfo : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("数据详情ID", recordInfo.getDetailId());
            map.put("设备IP", recordInfo.getIp());
            map.put("设备MAC", recordInfo.getMac());
            map.put("酒店ID", recordInfo.getHotelId());
            map.put("酒店名称", recordInfo.getHotelName());
            map.put("酒店房间ID", recordInfo.getHotelRoomId());
            map.put("酒店房间号", recordInfo.getHotelRoomNo());
            map.put("开机时间", recordInfo.getOpenTime());
            map.put("关机时间", recordInfo.getCloseTime());
            map.put("开关机时间差结果", recordInfo.getTimeResult());
            map.put(" createBy",  recordInfo.getCreateBy());
            map.put(" updateBy",  recordInfo.getUpdateBy());
            map.put(" createTime",  recordInfo.getCreateTime());
            map.put(" updateTime",  recordInfo.getUpdateTime());
            map.put(" isEnable",  recordInfo.getIsEnable());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }


	@Override
	public void splitTime(RecordDetailInfo resources) {
		// TODO Auto-generated method stub

		List<RecordInfo> recordCount = recordInfoRepository.findByDetailId(resources.getId());
		if(recordCount.size() > 0) {
			return;
		}
		LocalDateTime openTime = resources.getOpenTime();
		LocalDateTime closeTime = resources.getCloseTime();

		LocalDateTime splitTime = LocalDateTime.of(openTime.getYear(), openTime.getMonthValue(), openTime.getDayOfMonth(), 12, 0 , 0);
		if(closeTime==null){
			return;
		}
		JSONArray resultArray = new JSONArray();
		JSONObject tempTimeObj = null;
		while (true) {
			if (openTime.isBefore(splitTime)) {
				tempTimeObj = new JSONObject();
				tempTimeObj.put("openTime", openTime);
				tempTimeObj.put("closeTime", splitTime);
				resultArray.add(tempTimeObj);
				openTime = splitTime;
	        }
			splitTime = splitTime.plusDays(1);
			if (closeTime.isBefore(splitTime)) {
				LocalDateTime time = splitTime.minusDays(1);
	            if (closeTime.isAfter(time)) {
	            	if (openTime.isAfter(time)) {
	            		tempTimeObj = new JSONObject();
						tempTimeObj.put("openTime", openTime);
						tempTimeObj.put("closeTime", closeTime);
						resultArray.add(tempTimeObj);
	            	} else {
	            		tempTimeObj = new JSONObject();
						tempTimeObj.put("openTime", time);
						tempTimeObj.put("closeTime", closeTime);
						resultArray.add(tempTimeObj);
	            	}
	            }
	            break;
			}
		}

		RecordInfo recordInfo = new RecordInfo();
		recordInfo.setDetailId(resources.getId());
		recordInfo.setHotelId(resources.getHotelId());
		recordInfo.setHotelName(resources.getHotelName());
		recordInfo.setHotelRoomId(resources.getHotelRoomId());
		recordInfo.setHotelRoomNo(resources.getHotelRoomNo());
		recordInfo.setIp(resources.getIp());
		recordInfo.setIsEnable(1);
		recordInfo.setMac(resources.getMac());

		RecordInfo tempInfo = new RecordInfo();
		List<RecordInfo> records = new ArrayList<RecordInfo>();
		for(int index = 0; index < resultArray.size(); index ++) {
			tempTimeObj = resultArray.getJSONObject(index);

			tempInfo = BeanUtil.copyProperties(recordInfo,RecordInfo.class);
			tempInfo.setId(IdUtil.simpleUUID());
			tempInfo.setOpenTime((LocalDateTime)tempTimeObj.get("openTime"));
			tempInfo.setCloseTime((LocalDateTime)tempTimeObj.get("closeTime"));
			tempInfo.setBelongDate(tempInfo.getOpenTime().toLocalDate());

			Duration duration = twoTimeBetwwen(tempInfo.getOpenTime(),tempInfo.getCloseTime());
			tempInfo.setTimeResult(Integer.parseInt((duration.toMillis() / 1000) + ""));

			records.add(tempInfo);
		}
		recordInfoRepository.saveAll(records);
//		return resultArray;
	}


	public Duration twoTimeBetwwen(LocalDateTime openTime,LocalDateTime closeTime) {
		Duration duration = Duration.between(openTime, closeTime);
		return duration;
	}

}
